package com.felix.thread.rightLeftLock;

import lombok.Data;

import java.math.BigDecimal;

/**
 * DeadLockDemo1
 *
 * @author xjh
 * @version 1.0
 * @date 2019-02-02
 */
public class DeadLockDemo1 {
    private static final Object tieLock = new Object();

    public void transferMoney(final Account fromAccount, final Account toAccount, final BigDecimal amount) throws Exception {
        class Helper {
            public void transfer() throws Exception {
                if (fromAccount.getBalance().compareTo(amount) < 0) {
                    throw new Exception();
                } else {
                    fromAccount.debit(amount);
                    toAccount.credit(amount);
                }
            }
        }
        int fromHash = System.identityHashCode(fromAccount);
        int toHash = System.identityHashCode(toAccount);
        if (fromHash < toHash) {
            synchronized (fromAccount) {
                synchronized (toAccount) {
                    new Helper().transfer();
                }
            }
        } else if (fromHash > toHash) {
            synchronized (toAccount) {
                synchronized (fromAccount) {
                    new Helper().transfer();
                }
            }
        } else {
            synchronized (tieLock) {
                synchronized (fromAccount) {
                    synchronized (toAccount) {
                        new Helper().transfer();
                    }
                }
            }
        }
    }

    @Data
    public class Account {
        private BigDecimal balance;

        public void debit(BigDecimal amount) {
        }

        public void credit(BigDecimal amount) {
        }
    }

}
